{
 "cells": [
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2020-05-18T12:16:32.329915Z",
     "start_time": "2020-05-18T12:16:32.319667Z"
    }
   },
   "outputs": [],
   "source": [
    "def warn(*args, **kwargs):\n",
    "    pass\n",
    "import warnings\n",
    "warnings.warn = warn"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2020-05-18T12:16:39.423026Z",
     "start_time": "2020-05-18T12:16:37.486497Z"
    }
   },
   "outputs": [],
   "source": [
    "import numpy as np\n",
    "import os\n",
    "from time import time\n",
    "import cv2\n",
    "from time import time"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Build Data Loader"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 14,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2020-05-18T12:38:12.946362Z",
     "start_time": "2020-05-18T12:38:12.890419Z"
    }
   },
   "outputs": [],
   "source": [
    "from keras.utils import Sequence\n",
    "from keras.utils import np_utils\n",
    "\n",
    "class DataGenerator(Sequence):\n",
    "    \"\"\"Data Generator inherited from keras.utils.Sequence\n",
    "    Args: \n",
    "        directory: the path of data set, and each sub-folder will be assigned to one class\n",
    "        batch_size: the number of data points in each batch\n",
    "        shuffle: whether to shuffle the data per epoch\n",
    "    Note:\n",
    "        If you want to load file with other data format, please fix the method of \"load_data\" as you want\n",
    "    \"\"\"\n",
    "    def __init__(self, directory, batch_size=1, shuffle=True, data_augmentation=True):\n",
    "        # Initialize the params, 批大小、数据集地址、是否打乱、数据增强\n",
    "        self.batch_size = batch_size\n",
    "        self.directory = directory\n",
    "        self.shuffle = shuffle\n",
    "        self.data_aug = data_augmentation\n",
    "        # Load all the save_path of files, and create a dictionary that save the pair of \"data:label\"\n",
    "        self.X_path, self.Y_dict = self.search_data() # 索引数据\n",
    "        # Print basic statistics information\n",
    "        self.print_stats()\n",
    "        return None\n",
    "        \n",
    "    def search_data(self):\n",
    "        X_path = []\n",
    "        Y_dict = {}\n",
    "        # list all kinds of sub-folders\n",
    "        self.dirs = sorted(os.listdir(self.directory))  # ['Fight', 'NonFight']\n",
    "        one_hots = np_utils.to_categorical(range(len(self.dirs)))  # 自动转化为one-hot\n",
    "        for i,folder in enumerate(self.dirs):\n",
    "            folder_path = os.path.join(self.directory,folder)  # 依次进入到fight与nonfight目录\n",
    "            for file in os.listdir(folder_path):  # 索引路径下的所有文件\n",
    "                file_path = os.path.join(folder_path,file)  # 拼接为文件的完整路径\n",
    "                # append the each file path, and keep its label  \n",
    "                X_path.append(file_path)  # 将路径添加到X_path\n",
    "                Y_dict[file_path] = one_hots[i]  # 第一个目录与第二个目录分别为字典的两个值，路径为字典的键\n",
    "        return X_path, Y_dict  # 范围键（路径）与键值对（路径+是否打架）\n",
    "    \n",
    "    def print_stats(self):\n",
    "        # calculate basic information\n",
    "        self.n_files = len(self.X_path)\n",
    "        self.n_classes = len(self.dirs)\n",
    "        self.indexes = np.arange(len(self.X_path))\n",
    "        np.random.shuffle(self.indexes)\n",
    "        # Output states\n",
    "        print(\"Found {} files belonging to {} classes.\".format(self.n_files,self.n_classes))\n",
    "        for i,label in enumerate(self.dirs):\n",
    "            print('%10s : '%(label),i)\n",
    "        return None\n",
    "    \n",
    "    def __len__(self):\n",
    "        # calculate the iterations of each epoch, 向上取整\n",
    "        steps_per_epoch = np.ceil(len(self.X_path) / float(self.batch_size))\n",
    "        return int(steps_per_epoch)\n",
    "\n",
    "    def __getitem__(self, index):\n",
    "        \"\"\"Get the data of each batch\n",
    "        \"\"\"\n",
    "        # get the indexs of each batch，得到一批索引\n",
    "        batch_indexs = self.indexes[index*self.batch_size:(index+1)*self.batch_size]\n",
    "        # using batch_indexs to get path of current batch\n",
    "        batch_path = [self.X_path[k] for k in batch_indexs]\n",
    "        # get batch data\n",
    "        batch_x, batch_y = self.data_generation(batch_path)\n",
    "        return batch_x, batch_y\n",
    "\n",
    "    def on_epoch_end(self):\n",
    "        # shuffle the data at each end of epoch\n",
    "        if self.shuffle == True:\n",
    "            np.random.shuffle(self.indexes)\n",
    "\n",
    "    def data_generation(self, batch_path):\n",
    "        # load data into memory, you can change the np.load to any method you want\n",
    "        batch_x = [self.load_data(x) for x in batch_path]\n",
    "        batch_y = [self.Y_dict[x] for x in batch_path]\n",
    "        \n",
    "        # transfer the data format and take one-hot coding for labels\n",
    "        batch_x = np.array(batch_x)\n",
    "        batch_y = np.array(batch_y)\n",
    "        return batch_x, batch_y\n",
    "      \n",
    "    def normalize(self, data):\n",
    "        mean = np.mean(data)\n",
    "        std = np.std(data)\n",
    "        return (data-mean) / std\n",
    "    \n",
    "    def random_flip(self, video, prob):\n",
    "        s = np.random.rand()\n",
    "        if s < prob:\n",
    "            video = np.flip(m=video, axis=2)\n",
    "        return video    \n",
    "    \n",
    "    def uniform_sampling(self, video, target_frames=64):\n",
    "        # get total frames of input video and calculate sampling interval \n",
    "        len_frames = int(len(video))  # 计算传入视频长度\n",
    "        interval = int(np.ceil(len_frames/target_frames))  # 求帧间隔，向上取整\n",
    "        if interval != 1:  # 需要抽帧、补帧\n",
    "            # init empty list for sampled video and \n",
    "            sampled_video = []  # 抽帧后的视频\n",
    "            for i in range(0,len_frames,interval):\n",
    "                sampled_video.append(video[i])     \n",
    "            # calculate numer of padded frames and fix it \n",
    "            num_pad = target_frames - len(sampled_video)  # 如果总帧数不足，则进行补帧\n",
    "            if num_pad>0:\n",
    "                padding = [video[i] for i in range(-num_pad,0)]\n",
    "                sampled_video += padding   \n",
    "        else:  # 无需进一步处理\n",
    "            sampled_video = video\n",
    "        # get sampled video\n",
    "        return np.array(sampled_video, dtype=np.float32)\n",
    "        \n",
    "    def load_data(self, path):\n",
    "        # load a video to a list of images\n",
    "        data = []\n",
    "        cap = cv2.VideoCapture(path)\n",
    "#         length = int(cap.get(7))\n",
    "#         for i in range(length):  # 一次性读入全部帧\n",
    "#         length = 50\n",
    "        for i in range(55):  # 读取前55帧，取25-55帧，共30帧,1秒，采样15帧\n",
    "            ret, frame = cap.read()\n",
    "            if ret and i>=25 and i%2 == 0:  # 真实视频1秒15帧，手动抽帧\n",
    "                frame = cv2.resize(frame, (224,224))\n",
    "                data.append(frame)  # 将所有帧存储到data\n",
    "        cap.release()\n",
    "        # compute difference\n",
    "        new_data = [data[0]]  # 取出第一帧，(1, 224, 224, 3)\n",
    "        for i in range(1,len(data)):  # 逐帧计算帧差，(150, 224, 224, 3)\n",
    "            new_data.append(data[i]-data[i-1])\n",
    "        ### transfer the list of images to a tensor, and sample fixed numer of frames from original video\n",
    "        new_data = np.array(new_data).astype(np.float32)\n",
    "        new_data = self.uniform_sampling(video=new_data, target_frames=15)\n",
    "        # normalization\n",
    "        new_data = self.normalize(new_data)  # 对取得的帧数进行补帧\n",
    "        return new_data"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Build Model"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 33,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2020-05-18T16:46:43.769249Z",
     "start_time": "2020-05-18T16:46:43.766438Z"
    }
   },
   "outputs": [],
   "source": [
    "from keras.applications import Xception, ResNet50, InceptionV3, MobileNet, VGG19, DenseNet121, InceptionResNetV2, VGG16\n",
    "from keras.layers import LSTM, ConvLSTM2D\n",
    "import base_model"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 34,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2020-05-18T16:46:57.392636Z",
     "start_time": "2020-05-18T16:46:44.882593Z"
    }
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Model: \"model_6\"\n",
      "_________________________________________________________________\n",
      "Layer (type)                 Output Shape              Param #   \n",
      "=================================================================\n",
      "input_7 (InputLayer)         (None, 15, 224, 224, 3)   0         \n",
      "_________________________________________________________________\n",
      "time_distributed_4 (TimeDist (None, 15, 7, 7, 2048)    23587712  \n",
      "_________________________________________________________________\n",
      "conv_lst_m2d_4 (ConvLSTM2D)  (None, 7, 7, 256)         21234688  \n",
      "_________________________________________________________________\n",
      "max_pooling2d_8 (MaxPooling2 (None, 3, 3, 256)         0         \n",
      "_________________________________________________________________\n",
      "flatten_4 (Flatten)          (None, 2304)              0         \n",
      "_________________________________________________________________\n",
      "batch_normalization_4 (Batch (None, 2304)              9216      \n",
      "_________________________________________________________________\n",
      "dropout_10 (Dropout)         (None, 2304)              0         \n",
      "_________________________________________________________________\n",
      "dense_13 (Dense)             (None, 1000)              2305000   \n",
      "_________________________________________________________________\n",
      "activation_206 (Activation)  (None, 1000)              0         \n",
      "_________________________________________________________________\n",
      "dense_14 (Dense)             (None, 256)               256256    \n",
      "_________________________________________________________________\n",
      "dropout_11 (Dropout)         (None, 256)               0         \n",
      "_________________________________________________________________\n",
      "activation_207 (Activation)  (None, 256)               0         \n",
      "_________________________________________________________________\n",
      "dense_15 (Dense)             (None, 10)                2570      \n",
      "_________________________________________________________________\n",
      "dropout_12 (Dropout)         (None, 10)                0         \n",
      "_________________________________________________________________\n",
      "activation_208 (Activation)  (None, 10)                0         \n",
      "_________________________________________________________________\n",
      "dense_16 (Dense)             (None, 2)                 22        \n",
      "=================================================================\n",
      "Total params: 47,395,464\n",
      "Trainable params: 47,337,736\n",
      "Non-trainable params: 57,728\n",
      "_________________________________________________________________\n",
      "None\n"
     ]
    }
   ],
   "source": [
    "size = 224\n",
    "seq_len = 15  # 传入帧数\n",
    "initial_weights = 'Xavier'\n",
    "cnn_arch = ResNet50\n",
    "pre_weights = 'imagenet'\n",
    "lstm_conf = (ConvLSTM2D, dict(filters=256, kernel_size=(3, 3), padding='same', return_sequences=False))\n",
    "cnn_train_type = 'retrain'\n",
    "dropout = 0.0\n",
    "classes=2\n",
    "\n",
    "# /root/.keras/models/\n",
    "model = base_model.build(size=size, seq_len=seq_len,  initial_weights=initial_weights,\n",
    "                                   cnn_class=cnn_arch, pre_weights=pre_weights, lstm_conf=lstm_conf,\n",
    "                                   cnn_train_type=cnn_train_type, dropout=dropout, classes=classes)\n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Set Callbacks"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "- Learning Rate scheduler\n",
    "- [EarlyStopping](https://github.com/KPollux/LearnGitAndTF2.0/blob/master/BasicRegression.py)\n",
    "- [ModelCheckpoint 并行](https://blog.csdn.net/u012862372/article/details/80367607)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 35,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2020-05-18T16:47:06.870618Z",
     "start_time": "2020-05-18T16:47:06.842228Z"
    }
   },
   "outputs": [],
   "source": [
    "import keras.backend as K\n",
    "from keras.callbacks import LearningRateScheduler, EarlyStopping, ModelCheckpoint\n",
    "\n",
    "\n",
    "def scheduler(epoch):\n",
    "    if epoch % 10 == 0 and epoch != 0:\n",
    "        lr = K.get_value(parallel_model.optimizer.lr)\n",
    "        K.set_value(parallel_model.optimizer.lr, lr * 0.5)\n",
    "    return K.get_value(parallel_model.optimizer.lr)\n",
    "\n",
    "\n",
    "class ParallelModelCheckpoint(ModelCheckpoint):\n",
    "    def __init__(self, model, filepath, monitor='val_loss', verbose=0,\n",
    "                 save_best_only=False, save_weights_only=False,\n",
    "                 mode='auto', period=1):\n",
    "        self.single_model = model\n",
    "        super(ParallelModelCheckpoint, self).__init__(filepath, monitor,\n",
    "                                                      verbose, save_best_only, save_weights_only, mode, period)\n",
    "\n",
    "    def set_model(self, model):\n",
    "        super(ParallelModelCheckpoint, self).set_model(self.single_model)\n",
    "\n",
    "\n",
    "reduce_lr = LearningRateScheduler(scheduler)\n",
    "early_stop = EarlyStopping(monitor='val_loss', patience=10)\n",
    "\n",
    "filepath = \"weights-improvement-{epoch:02d}-{val_accuracy:.2f}.h5\"\n",
    "check_point = ParallelModelCheckpoint(model, filepath, monitor='val_accuracy', verbose=1, save_best_only=False,\n",
    "                                      mode='max')\n",
    "# checkpoint = ModelCheckpoint(filepath, monitor='val_acc', verbose=1, save_best_only=True,\n",
    "# mode='max')\n",
    "\n",
    "callbacks_list = [reduce_lr, early_stop, check_point]"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Set the GPUs and make it parallel"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 36,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2020-05-18T16:47:13.835667Z",
     "start_time": "2020-05-18T16:47:08.250535Z"
    }
   },
   "outputs": [],
   "source": [
    "os.environ[\"CUDA_VISIBLE_DEVICES\"] = \"0,1\"\n",
    "\n",
    "from keras.utils import multi_gpu_model \n",
    "parallel_model = multi_gpu_model(model, gpus=2)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "ExecuteTime": {
     "end_time": "2020-03-24T14:07:13.958588Z",
     "start_time": "2020-03-24T14:07:13.955417Z"
    }
   },
   "source": [
    "### Model Compiling"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 37,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2020-05-18T16:47:15.709510Z",
     "start_time": "2020-05-18T16:47:15.633102Z"
    }
   },
   "outputs": [],
   "source": [
    "from keras.optimizers import Adam, SGD\n",
    "\n",
    "sgd = SGD(lr=0.003, decay=1e-6, momentum=0.9, nesterov=True)\n",
    "parallel_model.compile(optimizer=sgd, loss='categorical_crossentropy', metrics=['accuracy'])"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Model Training"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "- set essential params"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 38,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2020-05-18T16:47:16.480576Z",
     "start_time": "2020-05-18T16:47:16.473073Z"
    }
   },
   "outputs": [],
   "source": [
    "num_epochs  = 50\n",
    "num_workers = 16\n",
    "batch_size  = 8"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "- init data generator"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 39,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2020-05-18T16:47:19.037596Z",
     "start_time": "2020-05-18T16:47:19.001827Z"
    }
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Found 1600 files belonging to 2 classes.\n",
      "     Fight :  0\n",
      "  NonFight :  1\n",
      "Found 400 files belonging to 2 classes.\n",
      "     Fight :  0\n",
      "  NonFight :  1\n"
     ]
    }
   ],
   "source": [
    "Dataset_dir = '/ssd/pyr'\n",
    "dataset = 'RWF-2000'\n",
    "\n",
    "# init the data generator for training set\n",
    "train_generator = DataGenerator(directory='{}/{}/train'.format(Dataset_dir, dataset), \n",
    "                                batch_size=batch_size, \n",
    "                                data_augmentation=True)\n",
    "\n",
    "# init the data generator for validation set\n",
    "val_generator = DataGenerator(directory='{}/{}/val'.format(Dataset_dir, dataset),\n",
    "                              batch_size=batch_size,\n",
    "                              data_augmentation=False)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "- start to train"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 40,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2020-05-18T17:49:22.168975Z",
     "start_time": "2020-05-18T16:47:21.730972Z"
    }
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Epoch 1/50\n",
      "200/200 [==============================] - 140s 698ms/step - loss: 0.6538 - accuracy: 0.6294 - val_loss: 0.6828 - val_accuracy: 0.4925\n",
      "\n",
      "Epoch 00001: saving model to weights-improvement-01-0.49.h5\n",
      "Epoch 2/50\n",
      "200/200 [==============================] - 119s 597ms/step - loss: 0.5860 - accuracy: 0.6825 - val_loss: 1.2355 - val_accuracy: 0.5650\n",
      "\n",
      "Epoch 00002: saving model to weights-improvement-02-0.56.h5\n",
      "Epoch 3/50\n",
      "200/200 [==============================] - 124s 622ms/step - loss: 0.5664 - accuracy: 0.7088 - val_loss: 0.6846 - val_accuracy: 0.7125\n",
      "\n",
      "Epoch 00003: saving model to weights-improvement-03-0.71.h5\n",
      "Epoch 4/50\n",
      "200/200 [==============================] - 126s 631ms/step - loss: 0.5378 - accuracy: 0.7237 - val_loss: 0.5357 - val_accuracy: 0.7100\n",
      "\n",
      "Epoch 00004: saving model to weights-improvement-04-0.71.h5\n",
      "Epoch 5/50\n",
      "200/200 [==============================] - 129s 647ms/step - loss: 0.5053 - accuracy: 0.7412 - val_loss: 0.4805 - val_accuracy: 0.7175\n",
      "\n",
      "Epoch 00005: saving model to weights-improvement-05-0.72.h5\n",
      "Epoch 6/50\n",
      "200/200 [==============================] - 134s 668ms/step - loss: 0.4606 - accuracy: 0.7912 - val_loss: 0.7772 - val_accuracy: 0.6950\n",
      "\n",
      "Epoch 00006: saving model to weights-improvement-06-0.69.h5\n",
      "Epoch 7/50\n",
      "200/200 [==============================] - 136s 680ms/step - loss: 0.4187 - accuracy: 0.8087 - val_loss: 0.8380 - val_accuracy: 0.6350\n",
      "\n",
      "Epoch 00007: saving model to weights-improvement-07-0.63.h5\n",
      "Epoch 8/50\n",
      "200/200 [==============================] - 141s 706ms/step - loss: 0.4084 - accuracy: 0.8181 - val_loss: 0.2538 - val_accuracy: 0.6000\n",
      "\n",
      "Epoch 00008: saving model to weights-improvement-08-0.60.h5\n",
      "Epoch 9/50\n",
      "200/200 [==============================] - 141s 704ms/step - loss: 0.4360 - accuracy: 0.7969 - val_loss: 0.7408 - val_accuracy: 0.6700\n",
      "\n",
      "Epoch 00009: saving model to weights-improvement-09-0.67.h5\n",
      "Epoch 10/50\n",
      "200/200 [==============================] - 146s 730ms/step - loss: 0.4007 - accuracy: 0.8075 - val_loss: 0.7143 - val_accuracy: 0.7150\n",
      "\n",
      "Epoch 00010: saving model to weights-improvement-10-0.71.h5\n",
      "Epoch 11/50\n",
      "200/200 [==============================] - 152s 760ms/step - loss: 0.3069 - accuracy: 0.8662 - val_loss: 0.7378 - val_accuracy: 0.6700\n",
      "\n",
      "Epoch 00011: saving model to weights-improvement-11-0.67.h5\n",
      "Epoch 12/50\n",
      "200/200 [==============================] - 147s 736ms/step - loss: 0.2231 - accuracy: 0.9069 - val_loss: 0.5413 - val_accuracy: 0.7050\n",
      "\n",
      "Epoch 00012: saving model to weights-improvement-12-0.70.h5\n",
      "Epoch 13/50\n",
      "200/200 [==============================] - 151s 756ms/step - loss: 0.1892 - accuracy: 0.9275 - val_loss: 1.4970 - val_accuracy: 0.7050\n",
      "\n",
      "Epoch 00013: saving model to weights-improvement-13-0.70.h5\n",
      "Epoch 14/50\n",
      "200/200 [==============================] - 157s 786ms/step - loss: 0.1957 - accuracy: 0.9262 - val_loss: 2.0187 - val_accuracy: 0.6625\n",
      "\n",
      "Epoch 00014: saving model to weights-improvement-14-0.66.h5\n",
      "Epoch 15/50\n",
      "200/200 [==============================] - 158s 791ms/step - loss: 0.1596 - accuracy: 0.9350 - val_loss: 0.0723 - val_accuracy: 0.6950\n",
      "\n",
      "Epoch 00015: saving model to weights-improvement-15-0.69.h5\n",
      "Epoch 16/50\n",
      "200/200 [==============================] - 156s 782ms/step - loss: 0.1540 - accuracy: 0.9425 - val_loss: 0.7107 - val_accuracy: 0.6325\n",
      "\n",
      "Epoch 00016: saving model to weights-improvement-16-0.63.h5\n",
      "Epoch 17/50\n",
      "200/200 [==============================] - 155s 777ms/step - loss: 0.1222 - accuracy: 0.9506 - val_loss: 2.5619 - val_accuracy: 0.6975\n",
      "\n",
      "Epoch 00017: saving model to weights-improvement-17-0.70.h5\n",
      "Epoch 18/50\n",
      "200/200 [==============================] - 160s 799ms/step - loss: 0.1569 - accuracy: 0.9406 - val_loss: 1.8202 - val_accuracy: 0.6625\n",
      "\n",
      "Epoch 00018: saving model to weights-improvement-18-0.66.h5\n",
      "Epoch 19/50\n",
      "200/200 [==============================] - 157s 787ms/step - loss: 0.1154 - accuracy: 0.9575 - val_loss: 0.9876 - val_accuracy: 0.7225\n",
      "\n",
      "Epoch 00019: saving model to weights-improvement-19-0.72.h5\n",
      "Epoch 20/50\n",
      "200/200 [==============================] - 158s 792ms/step - loss: 0.1127 - accuracy: 0.9544 - val_loss: 2.7396 - val_accuracy: 0.6175\n",
      "\n",
      "Epoch 00020: saving model to weights-improvement-20-0.62.h5\n",
      "Epoch 21/50\n",
      "200/200 [==============================] - 156s 781ms/step - loss: 0.0952 - accuracy: 0.9694 - val_loss: 0.9268 - val_accuracy: 0.6775\n",
      "\n",
      "Epoch 00021: saving model to weights-improvement-21-0.68.h5\n",
      "Epoch 22/50\n",
      "200/200 [==============================] - 157s 784ms/step - loss: 0.0737 - accuracy: 0.9737 - val_loss: 1.2431 - val_accuracy: 0.7125\n",
      "\n",
      "Epoch 00022: saving model to weights-improvement-22-0.71.h5\n",
      "Epoch 23/50\n",
      "200/200 [==============================] - 163s 814ms/step - loss: 0.0684 - accuracy: 0.9769 - val_loss: 0.3341 - val_accuracy: 0.6875\n",
      "\n",
      "Epoch 00023: saving model to weights-improvement-23-0.69.h5\n",
      "Epoch 24/50\n",
      "200/200 [==============================] - 160s 801ms/step - loss: 0.0680 - accuracy: 0.9800 - val_loss: 1.9260 - val_accuracy: 0.6950\n",
      "\n",
      "Epoch 00024: saving model to weights-improvement-24-0.69.h5\n",
      "Epoch 25/50\n",
      "200/200 [==============================] - 161s 805ms/step - loss: 0.0343 - accuracy: 0.9856 - val_loss: 1.0923 - val_accuracy: 0.6800\n",
      "\n",
      "Epoch 00025: saving model to weights-improvement-25-0.68.h5\n"
     ]
    }
   ],
   "source": [
    "hist = parallel_model.fit_generator(\n",
    "    generator=train_generator, \n",
    "    validation_data=val_generator,\n",
    "    callbacks=callbacks_list,\n",
    "    verbose=1, \n",
    "    epochs=num_epochs,\n",
    "    workers=num_workers ,\n",
    "    max_queue_size=2,\n",
    "    steps_per_epoch=len(train_generator),\n",
    "    validation_steps=len(val_generator))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "1、检视数据集\n",
    "\n",
    "2、分室内室外"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 45,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2020-05-18T18:02:34.030285Z",
     "start_time": "2020-05-18T18:02:34.005896Z"
    }
   },
   "outputs": [],
   "source": [
    "import matplotlib.pyplot as plt\n",
    "import pandas as pd\n",
    "\n",
    "# %% 训练过程数据可视化\n",
    "def plot_history(history):\n",
    "    hist = pd.DataFrame(history.history)\n",
    "    hist['epoch'] = history.epoch\n",
    "\n",
    "    # 绘制训练集与测试集的loss图像\n",
    "    plt.figure()\n",
    "    plt.xlabel('Epoch')\n",
    "    plt.ylabel('Loss')\n",
    "    plt.plot(hist['epoch'], hist['loss'],\n",
    "             label='Train Loss')  # 以批次为横坐标，mae为纵坐标，并制定图例名称\n",
    "    plt.plot(hist['epoch'], hist['val_loss'],\n",
    "             label='Val Loss')\n",
    "#     plt.ylim([0, 5])\n",
    "    plt.legend()  # 加上图例\n",
    "    plt.grid()  # 生成网格\n",
    "\n",
    "    # 绘制训练集与测试集的acc图像\n",
    "    plt.figure()\n",
    "    plt.xlabel('Epoch')\n",
    "    plt.ylabel('Accuracy')\n",
    "    plt.plot(hist['epoch'], hist['accuracy'],\n",
    "             label='Train Acc')\n",
    "    plt.plot(hist['epoch'], hist['val_accuracy'],\n",
    "             label='Val Acc')\n",
    "#     plt.ylim([0, 20])\n",
    "    plt.legend()\n",
    "    plt.grid()  # 生成网格\n",
    "    plt.show()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 46,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2020-05-18T18:02:34.894597Z",
     "start_time": "2020-05-18T18:02:34.201396Z"
    }
   },
   "outputs": [
    {
     "data": {
      "image/png": "iVBORw0KGgoAAAANSUhEUgAAAYYAAAEGCAYAAABhMDI9AAAABHNCSVQICAgIfAhkiAAAAAlwSFlzAAALEgAACxIB0t1+/AAAADh0RVh0U29mdHdhcmUAbWF0cGxvdGxpYiB2ZXJzaW9uMy4xLjMsIGh0dHA6Ly9tYXRwbG90bGliLm9yZy+AADFEAAAgAElEQVR4nO29d3xb5b34/34sz1i2k3jGdoazyB5OCGHGBMooUGbLKHzbQsullNs9aH8tpfRyL6W9HbntbS9QaAsUWjZlhZGYQEMgo9nbGcTxSOI4thVPWc/vj0eyZcdD4xxJtj7v18uvIx2dc/R5LFuf89lKa40gCIIg+EiItgCCIAhCbCGKQRAEQeiBKAZBEAShB6IYBEEQhB6IYhAEQRB6kBhtAYIlJydHT5gwIaRzT548SXp6urUCDSHief3xvHaI7/XL2s3a169ff0xrnRvIeUNOMUyYMIF169aFdG55eTllZWXWCjSEiOf1x/PaIb7XL2svA0ApdTDQ88SVJAiCIPRAFIMgCILQA1EMgiAIQg+GXIyhLzo6OqisrKS1tXXA47KystixY0eEpIo9gl1/amoqxcXFJCUl2SiVIAixxrBQDJWVlWRkZDBhwgSUUv0e19TUREZGRgQliy2CWb/Wmrq6OiorKykpKbFZMkEQYolh4UpqbW0lOzt7QKUgBIdSiuzs7EGtMEEQhh/DQjEAohRsQH6nghCfDBvFIAjCMKe1ETY9DTIqwHZEMVhAXV0d8+bNY968eRQUFFBUVNT1vL29PaBrfOELX2DXrl0Bv+cjjzzC17/+9VBFFoShx9Zn4YV/g+P7oi3JsGdYBJ+jTXZ2Nhs3bgTg3nvvxel08u1vf7vHMVprtNYkJPStix977DHb5RSEIU1jldk2VUP2pOjKMswRi8FG9u7dy6xZs7jjjjsoLS2lurqa22+/nYULFzJz5kzuu+++rmPPOeccNm7ciNvtZuTIkdx9993MnTuXM888kyNHjgT8nk888QSzZ89m1qxZ/OAHPwDA7XZzyy23sHjxYmbNmsWyZcsA+NWvfsWMGTOYO3cuN998s7WLFwSraarpuRVsY9hZDD/5xza2VzX2+VpnZycOhyPoa84ozOTHV8wMSZ7t27fz2GOP8Yc//AGABx54gNGjR+N2uzn//PO57rrrmDFjRo9zGhoaWLJkCQ888ADf/OY3efTRR7n77rsHfa/Kykp++MMfsm7dOrKysrjwwgt55ZVXyM3N5dixY6xZs4aMjAxOnDgBwIMPPsjBgwdJTk7u2icIMYur1rsN/EZJCA2xGGxm0qRJnH766V3Pn3rqKUpLSyktLWXHjh1s3779lHPS0tK49NJLAViwYAEHDhwI6L0+/PBDli5dSk5ODklJSdx0002sWrWKyZMns2vXLr773e+yfPlysrKyAJg5cyY333wzTz75pBSxCbFPU7XZusRisJthZzEMdGcfjQI3/3a/e/bs4Te/+Q0fffQRI0eO5Oabb+6zTiA5ObnrscPhwO12B/Reup9sjezsbDZv3szzzz/PsmXLeO6553jooYdYvnw57777Li+99BL/8R//wdatW0OyqAQhIjSJxRApxGKIII2NjWRkZJCZmUl1dTXLly+39PqLFy9m5cqV1NXV4Xa7efrpp1myZAlHjx5Fa83VV1/NT37yEzZs2EBnZyeVlZUsXbqUn//85xw9epTm5mZL5REEy+h0w8mj5rHEGGxn2FkMsUxpaSkzZsxg1qxZTJw4kbPPPjus6/3xj3/k2Wef7Xq+bt067rvvPsrKytBac8UVV3DZZZexYcMGbrvttq4Yy89+9jPcbjc33XQTTU1NeDwevve978V1uxAhxjl5BPBaxGIx2I7qz/0QqyxcuFD3HtSzY8cOpk+fPui50isp+PUH+ruNdeJ5WAsMg/Uf3gAPnw/OfPC44buB1zIM+bWHQa9BPeu11gsDOU9cSYIgxD6+jKQxc6G5Djo7oivPMEcUgyAIsY8vI2nMPLMVd5KtiGIQBCH2aaoFFBTMMs99FoRgC6IYBEHoycljsPGvsdWsrqka0nMgs9g8F8VgK6IYBEHoyaan4cUvw9HAmzrajqsWnAWQkd/9XLANUQyCIPTE588/tCa6cvjTVAMZBZCe530uisFObFMMSqmxSqmVSqkdSqltSqmv9XFMmVKqQSm10ftzj13y2ElZWdkpxWq//vWvufPOOwc8z+l0BrVfECKCL7D7cawphnxITIa00WIx2IydFoMb+JbWejqwGPiKUmpGH8e9p7We5/25r4/XY54bb7yRp59+use+p59+mhtvvDFKEglCGPi+dD/+ILpy+PB0mgI3Z4F57swXxWAztikGrXW11nqD93ETsAMosuv9osl1113HK6+8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\n",
      "text/plain": [
       "<Figure size 432x288 with 1 Axes>"
      ]
     },
     "metadata": {
      "needs_background": "light"
     },
     "output_type": "display_data"
    },
    {
     "data": {
      "image/png": "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\n",
      "text/plain": [
       "<Figure size 432x288 with 1 Axes>"
      ]
     },
     "metadata": {
      "needs_background": "light"
     },
     "output_type": "display_data"
    }
   ],
   "source": [
    "%matplotlib inline  \n",
    "\n",
    "plot_history(hist)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 25,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2020-05-18T16:42:50.713621Z",
     "start_time": "2020-05-18T16:42:50.347623Z"
    }
   },
   "outputs": [],
   "source": [
    "model.save('my_model_15_96.h5')"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "parallel_model = load_model('my_model.h5')"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.7.6"
  },
  "toc": {
   "base_numbering": 1,
   "nav_menu": {},
   "number_sections": true,
   "sideBar": true,
   "skip_h1_title": false,
   "title_cell": "Table of Contents",
   "title_sidebar": "Contents",
   "toc_cell": false,
   "toc_position": {},
   "toc_section_display": true,
   "toc_window_display": false
  },
  "varInspector": {
   "cols": {
    "lenName": 16,
    "lenType": 16,
    "lenVar": 40
   },
   "kernels_config": {
    "python": {
     "delete_cmd_postfix": "",
     "delete_cmd_prefix": "del ",
     "library": "var_list.py",
     "varRefreshCmd": "print(var_dic_list())"
    },
    "r": {
     "delete_cmd_postfix": ") ",
     "delete_cmd_prefix": "rm(",
     "library": "var_list.r",
     "varRefreshCmd": "cat(var_dic_list()) "
    }
   },
   "types_to_exclude": [
    "module",
    "function",
    "builtin_function_or_method",
    "instance",
    "_Feature"
   ],
   "window_display": false
  }
 },
 "nbformat": 4,
 "nbformat_minor": 2
}
